package com.gitee.cui.concurrency.concurrent;

import com.gitee.cui.util.Print;
import com.gitee.cui.util.ThreadUtil;
import com.google.common.util.concurrent.*;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用Guava的Future异步回调方式实现泡茶功能
 *
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/12/10 10:10
 **/
public class GuavaFutureDemo {

    private static final int SLEEP_GAP = 3000;

    static class HotWaterJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            try {
                Print.tcfo("清洗水壶");
                Print.tcfo("灌入凉水");
                Print.tcfo("放在火上");
                Thread.sleep(SLEEP_GAP);
                Print.tcfo("水烧好了");
            } catch (Exception e) {
                Print.tcfo("烧水任务失败");
                return false;
            }
            Print.tcfo("烧水任务执行完成");
            return true;
        }
    }

    static class WashJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            try {
                Print.tcfo("清洗茶壶");
                Print.tcfo("清洗茶杯");
                Thread.sleep(SLEEP_GAP);
                Print.tcfo("泡茶");
            } catch (Exception e) {
                Print.tcfo("清洗任务失败");
                return false;
            }
            Print.tcfo("清洗任务执行完成");
            return true;
        }
    }

    static class DrinkTea {

        private boolean waterOk = false;

        private boolean cupOk = false;

        public void drinkTea() {
            if (waterOk && cupOk) {
                Print.tcfo("成功泡茶喝");
            }
        }
    }

    public static void main(String[] args) {
        Thread.currentThread().setName("泡茶喝线程");
        DrinkTea drinkTea = new DrinkTea();
        HotWaterJob waterJob = new HotWaterJob();
        WashJob washJob = new WashJob();

        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        ListeningExecutorService gPool = MoreExecutors.listeningDecorator(threadPool);

        ListenableFuture<Boolean> hFuture = gPool.submit(waterJob);

        FutureCallback<Boolean> hCallBack = new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                if (result) {
                    drinkTea.waterOk = true;
                    drinkTea.drinkTea();
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Print.tcfo("烧水失败，没有茶喝了");
            }
        };

        Futures.addCallback(hFuture, hCallBack);

        ListenableFuture<Boolean> wFuture = gPool.submit(washJob);
        Futures.addCallback(wFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                if (result) {
                    drinkTea.cupOk = true;
                    drinkTea.drinkTea();
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Print.tcfo("清洗失败，没有茶喝了");
            }
        });

        Print.tcfo("干点其他事情……");
        ThreadUtil.sleepSeconds(1);
        Print.tcfo("执行完成");
    }
}
